package priv.utrix.micro.config;

import cn.hutool.core.thread.ThreadFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 统一线程池配置
 *
 * @author utrix
 * @date 2021/1/19
 */
@Configuration
public class ThreadPoolTaskConfig {

    /**
     * 定时任务之核心线程数量
     */
    private static final int CORE_POOL_SIZE;
    /**
     * 最大线程池的数量默认是机器逻辑核数量
     */
    private static final int MAXIMUM_POOL_SIZE;
    /**
     * 线程存活时间，单位秒
     */
    private static final int KEEP_ALIVE_TIME = 60;
    /**
     * 队列的长度
     */
    private static final int QUEUE_CAPACITY = 20;
    /**
     * 线程工厂名称
     */
    private static final ThreadFactory FACTORY;

    /**
     * 线程池命名前缀
     */
    private static final String THREAD_NAME_PREFIX = "self-worker-";

    static {
        int computerCoreSize = Runtime.getRuntime().availableProcessors();
        CORE_POOL_SIZE = computerCoreSize << 1;
        MAXIMUM_POOL_SIZE = computerCoreSize << 2;
        FACTORY = new ThreadFactoryBuilder().setNamePrefix(THREAD_NAME_PREFIX).setDaemon(true).build();
    }

    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor poolTaskExecutor = new ThreadPoolTaskExecutor();
        poolTaskExecutor.setCorePoolSize(CORE_POOL_SIZE);
        poolTaskExecutor.setMaxPoolSize(MAXIMUM_POOL_SIZE);
        poolTaskExecutor.setKeepAliveSeconds(KEEP_ALIVE_TIME);
        poolTaskExecutor.setQueueCapacity(QUEUE_CAPACITY);
        poolTaskExecutor.setThreadNamePrefix(THREAD_NAME_PREFIX);
        poolTaskExecutor.setThreadFactory(FACTORY);
        // 当缓存队列和MaxPoolSize达到上限后，执行拒绝策略
        poolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
        poolTaskExecutor.setAllowCoreThreadTimeOut(true);

        poolTaskExecutor.initialize();
        return poolTaskExecutor;
    }

}
